package com.test.demo.annotation.proxy.http.registrar;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;

import java.util.Set;

/**
 * @ClassName MyClassPathBeanDefinitionScanner
 * @Description
 * @Author laigl
 * @Date 2020/2/22 22:39
 **/
public class MyClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {

    private Class<? extends AbstractFactoryBean> factoryBeanImplClass;

    public MyClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }

    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        //BeanDefinitionHolder 封装了BeanDefinition,beanName以及aliases
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        logger.info("find beanDefinitions :" + beanDefinitions);
        if (!beanDefinitions.isEmpty()) {
            for (BeanDefinitionHolder holder : beanDefinitions) {
                GenericBeanDefinition defination = (GenericBeanDefinition) holder.getBeanDefinition();
                //通过反射的方式调用set方法注入属性
                defination.getPropertyValues().addPropertyValue("objectType", defination.getBeanClassName());
                // 设置bean工厂和对应的属性值
                defination.setBeanClass(this.factoryBeanImplClass);
                defination.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
            }
        }
        return beanDefinitions;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return (beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
        if (super.checkCandidate(beanName, beanDefinition)) {
            return true;
        } else {
            return false;
        }
    }

    public void setFactoryBeanImplClass(Class<? extends AbstractFactoryBean> factoryBeanImplClass) {
        this.factoryBeanImplClass = factoryBeanImplClass;
    }

}
